// This file is part of PleoCommand: // Interactively control Pleo with psychobiological parameters // // Copyright (C) 2010 Oliver Hoffmann - Hoffmann_Oliver@gmx.de // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Boston, USA. package pleocmd.itfc.gui.log; import java.awt.Component; import java.awt.Font; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.JTextPane; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableCellRenderer; import javax.swing.text.BadLocationException; import javax.swing.text.JTextComponent; import javax.swing.text.Style; import javax.swing.text.StyleConstants; import javax.swing.text.StyleContext; import javax.swing.text.StyledDocument; import pleocmd.Log; import pleocmd.StringManip; final class LogTableCellRenderer implements TableCellRenderer { private final DefaultTableCellRenderer def = new DefaultTableCellRenderer(); private final JTextField textField = new JTextField(); private final JTextPane textArea = new JTextPane(); public LogTableCellRenderer() { textField.setEditable(false); textArea.setEditable(false); // textArea.setLineWrap(true); // textArea.setWrapStyleWord(true); } @Override public Component getTableCellRendererComponent(final JTable table, final Object value, final boolean sel, final boolean foc, final int row, final int column) { def.getTableCellRendererComponent(table, null, sel, foc, 0, 0); if (!(value instanceof LogTableStyledCell)) return def; // returning "def" is the same as returning result of above method final LogTableStyledCell sc = (LogTableStyledCell) value; final JTextComponent comp = sc.isMultiLine() ? textArea : textField; comp.setBorder(def.getBorder()); // comp.setText(sc.getText()); comp.setForeground(sc.getForeground() == null ? def.getForeground() : sc.getForeground()); comp.setBackground(sc.getBackground() == null ? def.getBackground() : sc.getBackground()); Font font = def.getFont(); if (sc.isBold()) font = font.deriveFont(Font.BOLD); if (sc.isItalic()) font = font.deriveFont(Font.ITALIC); comp.setFont(font); // force the component to use all of the available space in its cell comp.setSize(table.getColumnModel().getColumn(column).getWidth(), Integer.MAX_VALUE); if (comp instanceof JTextPane) try { deHTML((JTextPane) comp, sc.getText()); } catch (final BadLocationException e) { // just ignore } else comp.setText(sc.getText()); return comp; } private void deHTML(final JTextPane tp, final String text) throws BadLocationException { tp.setText(""); final StyledDocument sd = tp.getStyledDocument(); Style style = sd.getStyle(StyleContext.DEFAULT_STYLE); if (!text.startsWith("<html>")) { sd.insertString(0, text, style); return; } StringBuilder sb = new StringBuilder(); int offset = 0; for (int i = 0; i < text.length(); ++i) { final char c = text.charAt(i); switch (c) { case '<': { sd.insertString(offset, sb.toString(), style); offset += sb.length(); sb = new StringBuilder(); final StringBuilder sb2 = new StringBuilder(); char c2; while ((c2 = text.charAt(++i)) != '>') sb2.append(c2); final String tag = sb2.toString(); if ("/font".equals(tag) || "/b".equals(tag) || "/i".equals(tag)) // we don't support recursive attributes, so just ... style = sd.getStyle(StyleContext.DEFAULT_STYLE); else if (tag.startsWith("b")) { style = sd.addStyle(null, style); StyleConstants.setBold(style, true); } else if (tag.startsWith("i")) { style = sd.addStyle(null, style); StyleConstants.setItalic(style, true); } else if (tag.startsWith("font color=#")) { style = sd.addStyle(null, style); StyleConstants.setForeground(style, StringManip.hexToColor(tag.substring(12))); } else if ("html".equals(tag) || "/html".equals(tag)) { // just ignore them silently } else Log.detail("Ignoring unknown tag '%s'", tag); break; } case '&': { final StringBuilder sb2 = new StringBuilder(); char c2; while ((c2 = text.charAt(++i)) != ';') sb2.append(c2); final String id = sb2.toString(); if ("lt".equals(id)) sb.append('<'); else if ("gt".equals(id)) sb.append('>'); else if ("amp".equals(id)) sb.append('&'); else if ("quot".equals(id)) sb.append('"'); else Log.detail("Ignoring unknown &%s;", id); // CS_IGNORE break; } default: sb.append(c); } } sd.insertString(offset, sb.toString(), style); } }